package com.plumecache.core;

import lombok.SneakyThrows;
import org.redisson.api.*;

import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author anson.yin
 * @date 2021/11/15 2:25 PM
 */
public abstract class RedisCacheService extends BaseCacheService {

    protected RedissonClient redissonClient;

    @Override
    public <T> void set(String key, T value) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        bucket.set(serialize(value));
    }

    @Override
    public <T> T get(String key, Class<T> clazz) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        return deserialize(bucket.get(), clazz);
    }

    @Override
    public <T> void set(String key, T value, Integer ttl) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        bucket.set(serialize(value), ttl, TimeUnit.SECONDS);
    }

    @Override
    public void delete(String key) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        bucket.delete();
    }

    @Override
    public void expire(String key, Integer ttl) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        bucket.expire(ttl, TimeUnit.SECONDS);
    }

    @Override
    public Long ttl(String key) {
        return redissonClient.getBucket(key).remainTimeToLive();
    }

    @Override
    public boolean exists(String key) {
        return redissonClient.getBucket(key).isExists();
    }

    @Override
    public long incr(String key) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        return atomicLong.incrementAndGet();
    }

    @Override
    public long incrBy(String key, Integer delta) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        return atomicLong.addAndGet(delta);
    }

    @Override
    public RedissonClient getRedissonClient() {
        return redissonClient;
    }

    @Override
    public <T> T hget(String key, String field, Class<T> clazz) {
        RMap<String, String> map = redissonClient.getMap(key);
        return deserialize(map.get(field), clazz);
    }

    @Override
    public <T> void hset(String key, String field, T value) {
        RMap<String, String> map = redissonClient.getMap(key);
        map.put(field, serialize(value));
    }

    @Override
    public long hdel(String key, String field) {
        RMap<String, String> map = redissonClient.getMap(key);
        return map.fastRemove(field);
    }

    @Override
    public <T> Map<String, T> hgetAll(String key, Class<T> clazz) {
        RMap<String, String> map = redissonClient.getMap(key);

        return map.readAllEntrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, r -> deserialize(r.getValue(), clazz)));
    }

    @Override
    public boolean lock(String key, Integer ttl) {
        RBucket<Object> bucket = redissonClient.getBucket(key);
        return bucket.trySet("1", ttl, TimeUnit.SECONDS);
    }

    @Override
    public void release(String key) {
        delete(key);
    }
}
